package com.xyxy.platform.modules.core.file.impl;

import com.google.common.collect.Lists;
import com.xyxy.platform.modules.core.file.ISystemFileService;
import com.xyxy.platform.modules.core.utils.Files3;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

/**
 * 简介: 系统文件处理
 *
 * @author Caizhenegda
 * @version 1.0
 * @Date 2015-12-29 11:23
 */
@Service("SystemFileServiceLocalImpl")
public class SystemFileServiceLocalImpl implements ISystemFileService {

    protected static final Logger logger = LoggerFactory.getLogger(SystemFileServiceLocalImpl.class);


    /**
     * 文件 存储 基本路径
     */
    @Value("${file.system.server.base.path:\"\"}")
    private String fileSystemServerBasePath;

    @PostConstruct
    public void init() {
        File tmpFileDir = new File(getTmpFilePath());
        File fileDir = new File(getFilePath());
        if (!tmpFileDir.exists()) tmpFileDir.mkdirs();
        if (!fileDir.exists()) fileDir.mkdirs();
    }

    /**
     * 文件访问url(根据子级访问临时与非临时)
     */
    @Value("${file.system.server.access.url:\"\"}")
    private String fileAccessUrl;

    /**
     * 非临时文件 存储 路径 (使用中的文件)
     */
    @Override
    public String getFilePath() {
        return fileSystemServerBasePath + File.separator + "files";
    }

    /**
     * 临时文件 存储 路径
     */
    @Override
    public String getTmpFilePath() {
        return fileSystemServerBasePath + File.separator + "filestmp";
    }

    /**
     * 存储文件为临时文件
     *
     * @param inputStream 文件流
     * @param fileName    原名, 会在其基础上加入 uuid-
     */
    @Override
    public String saveTmpFile(InputStream inputStream, String fileName) {
        fileName = UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf(".")).toLowerCase();
        try {
            FileUtils.copyInputStreamToFile(inputStream, new File(getTmpFilePath(), fileName));
        } catch (IOException e) {
            logger.error("存储临时文件失败, e: {}", e.getMessage());
        }
        return getTmpFileUrlByUri(fileName);
    }

    /**
     * 删除临时文件
     *
     * @param primaryFileName 文件名
     * @return
     */
    @Override
    @Async
    public boolean deleteTmpFile(String primaryFileName) {
        File file = new File(getTmpFilePath() + File.separator + primaryFileName);
        if (!file.exists() && !file.isFile()) {
            logger.warn("not found this tmp file: {}", primaryFileName);
            return false;
        }
        return file.delete();
    }

    /**
     * 改变临时文件状态
     * 将临时文件拷贝至使用文件目录(非临时文件目录)
     *
     * @param primaryFileName 文件名
     */
    @Override
    public void changeFileStatus(String primaryFileName) {
        File sourceFile = new File(getTmpFilePath() + File.separator + primaryFileName);
        File targetFile = new File(getFilePath() + File.separator + primaryFileName);
        if (targetFile.isFile() && targetFile.exists()) return;
        if (sourceFile.exists() && sourceFile.isFile()) {
            try {
                Files3.copy(sourceFile, targetFile);
            } catch (Exception e) {
                logger.info("Files3.copy error: {}", e.getMessage());
            }
        }
    }

    /**
     * 改变临时文件状态
     * 解析 html 中得图片地址, 目前仅支持: <image src="imageUrl" />
     * 1. 根据 imageUrl 获得对于的 文件名(uuid+文件名)
     * 2. 将临时文件拷贝到非临时文件目录去.
     * 3. 修改 htmlContent 中得imageUrl. 非临时
     *
     * @param htmlContent html 内容
     * @return 修改过的html内容
     */
    @Override
    public String changeImageFileStatusFromHtml(String htmlContent) {
        //更新html内容
        Document document = Jsoup.parse(htmlContent);
        List<String> fileNameList = Lists.newArrayList();
        Elements images = document.select("img[src]");
        for (Element element : images) {
            String imgUrl = element.attr("src");
            if (imgUrl.indexOf(tmpFilesDir) == -1) continue;
            String fileName = imgUrl.substring(imgUrl.lastIndexOf("/") + 1);
            if (StringUtils.isNotEmpty(fileName)) {
                imgUrl = this.getFileUrlByUri(fileName);
                element.attr("src", imgUrl);
                fileNameList.add(fileName);
            }
        }
        //copy 文件 (临时文件不用删, 有 job 会完成)
        for (String fileName : fileNameList) {
            this.changeFileStatus(fileName);
        }
        return document.select("body").html().toString();
    }

    /**
     * 从html中获得文件名(uuid+filename) List
     *
     * @param htmlContent
     * @return
     */
    @Override
    public List<String> getImageFileNameListFromHtml(String htmlContent) {
        List<String> fileNameList = Lists.newArrayList();
        Document document = Jsoup.parse(htmlContent);
        Elements images = document.select("img[src]");
        for (Element element : images) {
            String imgUrl = element.attr("src");
            String fileName = imgUrl.substring(imgUrl.lastIndexOf("/") + 1);
            if (StringUtils.isNotEmpty(fileName)) {
                fileNameList.add(fileName);
            }
        }
        return fileNameList;
    }

    /**
     * 根据 url 获得 唯一 FileName
     *
     * @param url
     * @return
     */
    @Override
    public String getFileNameFromUrl(String url) {
        if (StringUtils.isNotEmpty(url) && url.indexOf("/") != -1) {
            return url.substring(url.lastIndexOf("/") + 1);
        }
        return null;
    }

    /**
     * 根据 url 获得 唯一 FileName
     *
     * @param url
     * @return
     */
    @Override
    public String getUriByUrl(String url) {
        if (StringUtils.isNotEmpty(url) && url.indexOf("/") != -1) {
            return url.substring(url.lastIndexOf("/") + 1);
        }
        return null;
    }

    @Override
    public String getFileUrlByUri(String uri) {
        if (StringUtils.isNotEmpty(uri)) {
            return new StringBuffer(this.fileAccessUrl).append("/").append(filesDir).append("/").append(uri).toString();
        }
        return "";
    }

    @Override
    public String getTmpFileUrlByUri(String uri) {
        if (StringUtils.isNotEmpty(uri)) {
            return new StringBuffer(this.fileAccessUrl).append("/").append(tmpFilesDir).append("/").append(uri).toString();
        }
        return "";
    }

}
